package org.iteam.bank.mina.client;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.iteam.mina.message.BaseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class IoSessionConn {
	private String ip;
	private int port;
	private Long timeoutMillis = new Long(5 * 1000);
	private static final Logger log = LoggerFactory.getLogger(IoSessionConn.class);
	private ConnectFuture cf = null;
	private NioSocketConnector connector = null;
	private IoSession ioSession = null;

	public IoSessionConn(String ip, int port, NioSocketConnector connector) {
		super();
		this.ip = ip;
		this.port = port;
		this.connector = connector;
	}

	public IoSessionConn(String ip, int port, NioSocketConnector connector, Long timeoutMillis) {
		super();
		this.ip = ip;
		this.port = port;
		this.timeoutMillis = timeoutMillis;
		this.connector = connector;
	}

	public boolean isOpen() {
		if (ioSession != null) {
			if (ioSession.isConnected()) {
				return true;
			}
		}
		return false;
	}

	public void conn() {
		try {
			cf = connector.connect(new InetSocketAddress(ip, port));
			log.debug("等待连接创建完成......");
			cf.awaitUninterruptibly();// 等待连接创建完成
			log.debug("连接创建完成-->{}:{}", ip, port);
			ioSession = cf.getSession();
		} catch (Exception e) {
			log.error("mina 连接池 连发服务器{}:{}失败", ip, port);
		}
	}

	/**
	 * 
	 * 发送消息
	 * 
	 * @param request
	 * @param isTimeOut
	 *            是否设置超时时间
	 */
	public void write(BaseMessage request) {
		write(request, false);
	}

	/**
	 * 
	 * 发送消息
	 * 
	 * @param request
	 * @param isTimeOut
	 *            是否设置超时时间
	 * @return true 如果操作完成
	 */
	public boolean write(BaseMessage request, boolean isTimeOut) {
		if (ioSession == null) {
			log.debug("发送数据失败.....服务连接失败");
			return false;
		}
		WriteFuture writeFuture = ioSession.write(request);
		log.debug("发送数据成功.....等待数据处理完成");
		if (isTimeOut) {
			return writeFuture.awaitUninterruptibly(timeoutMillis, TimeUnit.MILLISECONDS);// 等待数据处理完成
		} else {
			writeFuture = writeFuture.awaitUninterruptibly();// 等待数据处理完成
		}
		return true;
	}

	/**
	 * 读取消息
	 * 
	 * @return
	 * @throws Exception
	 */
	public BaseMessage read() throws Exception {
		return read(false);
	}

	/**
	 * 读取消息
	 * 
	 * @param isTimeOut
	 *            是否设置超时时间
	 * @return
	 * @throws Exception
	 */
	public BaseMessage read(boolean isTimeOut) throws Exception {
		if (ioSession == null) {
			throw new Exception("响应消息错误,服务连接失败");
		}
		ReadFuture readFuture = ioSession.read();
		log.debug("等待接收服务器返回消息");
		Object object = null;
		if (isTimeOut) {
			if (readFuture.awaitUninterruptibly(timeoutMillis, TimeUnit.MILLISECONDS)) {
				object = readFuture.getMessage();
			} else {
				object = new Object();
			}
		} else {
			object = readFuture.awaitUninterruptibly().getMessage();
		}
		if (!(object instanceof BaseMessage)) {
			throw new Exception("响应消息错误");
		}
		return (BaseMessage) object;
	}

	public void close() {
		if (ioSession != null) {
			ioSession.close(true);
		}
	}

	public SocketAddress getRemoteAddress() {
		return ioSession.getRemoteAddress();
	}

	@Override
	protected void finalize() throws Throwable {
		close();
		super.finalize();
	}
}
